﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using System.Security;
using System.Xml.Linq;
using System.Reflection;

namespace BulldogCMS.Core
{
    public static class Extensions
    {
        public static T GetAttributeValue<T>(this XElement el, XName name)
        {
            if (el.Attribute(name) != null)
            {
                object value = el.Attribute(name).Value;

                if (typeof(T).IsEnum)
                {
                    string enumName = value as string;
                    return (T)(object)Enum.Parse(typeof(T), enumName);
                }

                if (typeof(T) == typeof(string)) return (T)value;
                if (typeof(T) == typeof(DateTime))
                {
                    return (T)(object)DateTime.Parse((string)value);
                }
                if (typeof(T) == typeof(int))
                {
                    object number = int.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(ushort))
                {
                    object number = ushort.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(long))
                {
                    object number = long.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(uint))
                {
                    object number = uint.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(byte))
                {
                    object number = byte.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(bool))
                {
                    string sValue = (value as string).ToLower();
                    if (sValue == "true")
                    {
                        return (T)(object)true;
                    }
                    else
                    {
                        return (T)(object)false;
                    }
                }

                return default(T);
            }
            else
            {
                return default(T);
            }
        }

        public static T GetElementValue<T>(this XElement el, XName name)
        {
            var pokus = el.Element(name.LocalName);
            if (el.Element(name) != null)
            {
                object value = el.Element(name).Value;

                if (typeof(T) == typeof(string)) return (T)value;
                if (typeof(T) == typeof(byte))
                {
                    object number = byte.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(ushort))
                {
                    object number = ushort.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(uint))
                {
                    object number = uint.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(int))
                {
                    object number = int.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(long))
                {
                    object number = long.Parse((string)value);
                    return (T)number;
                }
                if (typeof(T) == typeof(bool))
                {
                    string sValue = (value as string).ToLower();
                    if (sValue == "true")
                    {
                        return (T)(object)true;
                    }
                    else
                    {
                        return (T)(object)false;
                    }
                }

                return default(T);
            }
            else
            {
                return default(T);
            }
        }

        public static T GetAttributeValueEnum<T>(this XElement el, string name, params string[] items)
        {
            int index = -1;
            string value = el.Attribute(name).Value;
            foreach (string item in items)
            {
                index++;
                if (item == value) break;
            }
            return (T)Enum.ToObject(typeof(T), index + 1);
        }

        public static void SetAttributeOrLeaveEmpty<T>(this XElement el, string name, T obj)
        {
            if (obj != null)
            {
                if (typeof(T) == typeof(bool))
                {
                    bool value = (bool)(object)obj;
                    if (value)
                    {
                        el.Add(new XAttribute(name, "true"));
                    }
                }
                else
                {
                    el.Add(new XAttribute(name, obj.ToString()));
                }
            }
        }

        public static SecureString ToSecureString(this string value)
        {
            var secureString = new SecureString();
            if (!string.IsNullOrEmpty(value))
            {
                foreach (char c in value)
                {
                    secureString.AppendChar(c);
                }
            }
            secureString.MakeReadOnly();
            return secureString;
        }

        public static IEnumerable<T> GetNth<T>(this List<T> list, int n)
        {
            for (int i = 0; i < list.Count; i += n)
                yield return list[i];
        }

        public static string RenderPartialView(this Controller controller, string viewName, object model)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = controller.ControllerContext.RouteData.GetRequiredString("action");

            controller.ViewData.Model = model;
            using (var sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
                var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();
            }
        }

        public static string CutEnd(this string text, string endText)
        {
            if (text.EndsWith(endText))
            {
                return text.Substring(0, text.Length - endText.Length);
            }
            return text;
        }

        public static string CombineUrl(this string uri1, string uri2)
        {
            uri1 = uri1.TrimEnd('/');
            uri2 = uri2.TrimStart('/');
            return string.Format("{0}/{1}", uri1, uri2);
        }

        public static T Instantiate<T>(this Type type) where T:class
        {
            ConstructorInfo constuctorInfo = type.GetConstructor(System.Type.EmptyTypes);
            if (constuctorInfo != null)
            {
                return constuctorInfo.Invoke(new object[] { }) as T;
            }
            return null;
        }

        public static T Instantiate<T>(this string typeName) where T : class
        {
            Type type = Type.GetType(typeName);
            return type.Instantiate<T>();
        }

        public static string ToJSON(this object obj)
        {
            return Newtonsoft.Json.JsonConvert.SerializeObject(obj);
        }

        public static dynamic ToDynamicObject(this string jsonString)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);
        }

    }
}